home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / MAME / src / cpu / s2650 / s2650.c < prev    next >
C/C++ Source or Header  |  2000-05-04  |  47KB  |  1,545 lines

  1. /*************************************************************************
  2.  *
  3.  *      Portable Signetics 2650 cpu emulation
  4.  *
  5.  *        Written by Juergen Buchmueller for use with MAME
  6.  *
  7.  *************************************************************************/
  8.  
  9. #include <stdio.h>
  10. #include <strings.h>
  11. #include "driver.h"
  12. #include "state.h"
  13. #include "mamedbg.h"
  14. #include "s2650.h"
  15. #include "s2650cpu.h"
  16.  
  17. /* define this to have some interrupt information logged */
  18. #define VERBOSE 0
  19.  
  20. #if VERBOSE
  21. #include <stdio.h>
  22. #define LOG(x) logerror x
  23. #else
  24. #define LOG(x)
  25. #endif
  26.  
  27. /* define this to expand all EA calculations inline */
  28. #define INLINE_EA    1
  29.  
  30. static UINT8 s2650_reg_layout[] = {
  31.     S2650_PC, S2650_PS, S2650_R0, S2650_R1, S2650_R2, S2650_R3, -1,
  32.     S2650_SI, S2650_FO, S2650_R1A, S2650_R2A, S2650_R3A, -1,
  33.     S2650_HALT, S2650_IRQ_STATE, 0
  34. };
  35.  
  36. /* Layout of the debugger windows x,y,w,h */
  37. static UINT8 s2650_win_layout[] = {
  38.     32, 0,48, 4,    /* register window (top rows) */
  39.      0, 0,31,22,    /* disassembler window (left colums) */
  40.     32, 5,48, 8,    /* memory #1 window (right, upper middle) */
  41.     32,14,48, 8,    /* memory #2 window (right, lower middle) */
  42.      0,23,80, 1,    /* command line window (bottom rows) */
  43. };
  44.  
  45. int s2650_ICount = 0;
  46.  
  47. typedef struct {
  48.     UINT16    ppc;    /* previous program counter (page + iar) */
  49.     UINT16  page;   /* 8K page select register (A14..A13) */
  50.     UINT16  iar;    /* instruction address register (A12..A0) */
  51.     UINT16  ea;     /* effective address (A14..A0) */
  52.     UINT8   psl;    /* processor status lower */
  53.     UINT8   psu;    /* processor status upper */
  54.     UINT8   r;      /* absolute addressing dst/src register */
  55.     UINT8   reg[7]; /* 7 general purpose registers */
  56.     UINT8   halt;   /* 1 if cpu is halted */
  57.     UINT8   ir;     /* instruction register */
  58.     UINT16  ras[8]; /* 8 return address stack entries */
  59.     UINT8    irq_state;
  60.     int     (*irq_callback)(int irqline);
  61. }   s2650_Regs;
  62.  
  63. static s2650_Regs S;
  64.  
  65. /* condition code changes for a byte */
  66. static    UINT8 ccc[0x200] = {
  67.     0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,
  68.     0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,
  69.     0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,
  70.     0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,
  71.     0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,
  72.     0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,
  73.     0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,
  74.     0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,
  75.     0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
  76.     0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
  77.     0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
  78.     0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
  79.     0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
  80.     0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
  81.     0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
  82.     0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
  83.     0x04,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
  84.     0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
  85.     0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
  86.     0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
  87.     0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
  88.     0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
  89.     0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
  90.     0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,0x44,
  91.     0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,
  92.     0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,
  93.     0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,
  94.     0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,
  95.     0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,
  96.     0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,
  97.     0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,
  98.     0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,
  99. };
  100.  
  101. #define CHECK_IRQ_LINE                                            \
  102.     if (S.irq_state != CLEAR_LINE)                                \
  103.     {                                                            \
  104.         if( (S.psu & II) == 0 )                                 \
  105.         {                                                        \
  106.             int vector;                                         \
  107.             if (S.halt)                                         \
  108.             {                                                    \
  109.                 S.halt = 0;                                     \
  110.                 S.iar = (S.iar + 1) & PMSK;                     \
  111.             }                                                    \
  112.             vector = (*S.irq_callback)(0) & 0xff;                \
  113.             /* build effective address within first 8K page */    \
  114.             S.ea = S2650_relative[vector] & PMSK;                \
  115.             if (vector & 0x80)        /* indirect bit set ? */    \
  116.             {                                                    \
  117.                 int addr = S.ea;                                \
  118.                 s2650_ICount -= 2;                                \
  119.                 /* build indirect 32K address */                \
  120.                 S.ea = RDMEM(addr) << 8;                        \
  121.                 if (!(++addr & PMSK)) addr -= PLEN;             \
  122.                 S.ea = (S.ea + RDMEM(addr)) & AMSK;             \
  123.             }                                                    \
  124.             LOG(("S2650 interrupt to $%04x\n", S.ea));\
  125.             S.psu  = (S.psu & ~SP) | ((S.psu + 1) & SP) | II;    \
  126.             S.ras[S.psu & SP] = S.page + S.iar;                    \
  127.             S.page = S.ea & PAGE;                                \
  128.             S.iar  = S.ea & PMSK;                                \
  129.         }                                                        \
  130.     }
  131.  
  132. /***************************************************************
  133.  *
  134.  * set condition code (zero,plus,minus) from result
  135.  ***************************************************************/
  136. #define SET_CC(result)                                          \
  137.     S.psl = (S.psl & ~CC) | ccc[result]
  138.  
  139. /***************************************************************
  140.  *
  141.  * set condition code (zero,plus,minus) and overflow
  142.  ***************************************************************/
  143. #define SET_CC_OVF(result,value)                                \
  144.     S.psl = (S.psl & ~(OVF+CC)) |                                \
  145.         ccc[result + ( ( (result^value) << 1) & 256 )]
  146.  
  147. /***************************************************************
  148.  * ROP
  149.  * read next opcode
  150.  ***************************************************************/
  151. INLINE UINT8 ROP(void)
  152. {
  153.     UINT8 result = cpu_readop(S.page + S.iar);
  154.     S.iar = (S.iar + 1) & PMSK;
  155.     return result;
  156. }
  157.  
  158. /***************************************************************
  159.  * ARG
  160.  * read next opcode argument
  161.  ***************************************************************/
  162. INLINE UINT8 ARG(void)
  163. {
  164.     UINT8 result = cpu_readop_arg(S.page + S.iar);
  165.     S.iar = (S.iar + 1) & PMSK;
  166.     return result;
  167. }
  168.  
  169. /***************************************************************
  170.  * RDMEM
  171.  * read memory byte from addr
  172.  ***************************************************************/
  173. #define RDMEM(addr) cpu_readmem16(addr)
  174.  
  175. /***************************************************************
  176.  * handy table to build PC relative offsets
  177.  * from HR (holding register)
  178.  ***************************************************************/
  179. static    int     S2650_relative[0x100] =
  180. {
  181.       0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
  182.      16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
  183.      32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
  184.      48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
  185.     -64,-63,-62,-61,-60,-59,-58,-57,-56,-55,-54,-53,-52,-51,-50,-49,
  186.     -48,-47,-46,-45,-44,-43,-42,-41,-40,-39,-38,-37,-36,-35,-34,-33,
  187.     -32,-31,-30,-29,-28,-27,-26,-25,-24,-23,-22,-21,-20,-19,-18,-17,
  188.     -16,-15,-14,-13,-12,-11,-10, -9, -8, -7, -6, -5, -4, -3, -2, -1,
  189.       0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
  190.      16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
  191.      32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
  192.      48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
  193.     -64,-63,-62,-61,-60,-59,-58,-57,-56,-55,-54,-53,-52,-51,-50,-49,
  194.     -48,-47,-46,-45,-44,-43,-42,-41,-40,-39,-38,-37,-36,-35,-34,-33,
  195.     -32,-31,-30,-29,-28,-27,-26,-25,-24,-23,-22,-21,-20,-19,-18,-17,
  196.     -16,-15,-14,-13,-12,-11,-10, -9, -8, -7, -6, -5, -4, -3, -2, -1,
  197. };
  198.  
  199. /***************************************************************
  200.  * _REL_EA
  201.  * build effective address with relative addressing
  202.  ***************************************************************/
  203. #define _REL_EA(page)                                            \
  204. {                                                                \
  205.     UINT8 hr = ARG();    /* get 'holding register' */            \
  206.     /* build effective address within current 8K page */        \
  207.     S.ea = page + ((S.iar + S2650_relative[hr]) & PMSK);        \
  208.     if (hr & 0x80) { /* indirect bit set ? */                    \
  209.         int addr = S.ea;                                        \
  210.         s2650_ICount -= 2;                                        \
  211.         /* build indirect 32K address */                        \
  212.         S.ea = RDMEM(addr) << 8;                                \
  213.         if( (++addr & PMSK) == 0 ) addr -= PLEN; /* page wrap */\
  214.         S.ea = (S.ea + RDMEM(addr)) & AMSK;                     \
  215.     }                                                            \
  216. }
  217.  
  218. /***************************************************************
  219.  * _REL_ZERO
  220.  * build effective address with zero relative addressing
  221.  ***************************************************************/
  222. #define _REL_ZERO(page)                                            \
  223. {                                                                \
  224.     UINT8 hr = ARG();    /* get 'holding register' */            \
  225.     /* build effective address from 0 */                        \
  226.     S.ea = (S2650_relative[hr] & PMSK);                            \
  227.     if (hr & 0x80) { /* indirect bit set ? */                    \
  228.         int addr = S.ea;                                        \
  229.         s2650_ICount -= 2;                                        \
  230.         /* build indirect 32K address */                        \
  231.         S.ea = RDMEM(addr) << 8;                                \
  232.         if( (++addr & PMSK) == 0 ) addr -= PLEN; /* page wrap */\
  233.         S.ea = (S.ea + RDMEM(addr)) & AMSK;                     \
  234.     }                                                            \
  235. }
  236.  
  237. /***************************************************************
  238.  * _ABS_EA
  239.  * build effective address with absolute addressing
  240.  ***************************************************************/
  241. #define _ABS_EA()                                                \
  242. {                                                                \
  243.     UINT8 hr, dr;                                                \
  244.     hr = ARG();     /* get 'holding register' */                \
  245.     dr = ARG();     /* get 'data bus register' */               \
  246.     /* build effective address within current 8K page */        \
  247.     S.ea = S.page + (((hr << 8) + dr) & PMSK);                    \
  248.     /* indirect addressing ? */                                 \
  249.     if (hr & 0x80) {                                            \
  250.         int addr = S.ea;                                        \
  251.         s2650_ICount -= 2;                                        \
  252.         /* build indirect 32K address */                        \
  253.         /* build indirect 32K address */                        \
  254.         S.ea = RDMEM(addr) << 8;                                \
  255.         if( (++addr & PMSK) == 0 ) addr -= PLEN; /* page wrap */\
  256.         S.ea = (S.ea + RDMEM(addr)) & AMSK;                     \
  257.     }                                                            \
  258.     /* check indexed addressing modes */                        \
  259.     switch (hr & 0x60) {                                        \
  260.         case 0x00: /* not indexed */                            \
  261.             break;                                                \
  262.         case 0x20: /* auto increment indexed */                 \
  263.             S.reg[S.r] += 1;                                    \
  264.             S.ea = (S.ea & PAGE)+((S.ea+S.reg[S.r]) & PMSK);    \
  265.             S.r = 0; /* absolute addressing reg is R0 */        \
  266.             break;                                                \
  267.         case 0x40: /* auto decrement indexed */                 \
  268.             S.reg[S.r] -= 1;                                    \
  269.             S.ea = (S.ea & PAGE)+((S.ea+S.reg[S.r]) & PMSK);    \
  270.             S.r = 0; /* absolute addressing reg is R0 */        \
  271.             break;                                                \
  272.         case 0x60: /* indexed */                                \
  273.             S.ea = (S.ea & PAGE)+((S.ea+S.reg[S.r]) & PMSK);    \
  274.             S.r = 0; /* absolute addressing reg is R0 */        \
  275.             break;                                                \
  276.     }                                                            \
  277. }
  278.  
  279. /***************************************************************
  280.  * _BRA_EA
  281.  * build effective address with absolute addressing (branch)
  282.  ***************************************************************/
  283. #define _BRA_EA()                                                \
  284. {                                                                \
  285.     UINT8 hr, dr;                                                \
  286.     hr = ARG();     /* get 'holding register' */                \
  287.     dr = ARG();     /* get 'data bus register' */               \
  288.     /* build address in 32K address space */                    \
  289.     S.ea = ((hr << 8) + dr) & AMSK;                             \
  290.     /* indirect addressing ? */                                 \
  291.     if (hr & 0x80) {                                            \
  292.         int addr = S.ea;                                        \
  293.         s2650_ICount -= 2;                                        \
  294.         /* build indirect 32K address */                        \
  295.         S.ea = RDMEM(addr) << 8;                                \
  296.         if( (++addr & PMSK) == 0 ) addr -= PLEN; /* page wrap */\
  297.         S.ea = (S.ea + RDMEM(addr)) & AMSK;                     \
  298.     }                                                            \
  299. }
  300.  
  301. /***************************************************************
  302.  * SWAP_REGS
  303.  * Swap registers r1-r3 with r4-r6 (the second set)
  304.  * This is done everytime the RS bit in PSL changes
  305.  ***************************************************************/
  306. #define SWAP_REGS                                                \
  307. {                                                                \
  308.     UINT8 tmp;                                                    \
  309.     tmp = S.reg[1];                                             \
  310.     S.reg[1] = S.reg[4];                                        \
  311.     S.reg[4] = tmp;                                             \
  312.     tmp = S.reg[2];                                             \
  313.     S.reg[2] = S.reg[5];                                        \
  314.     S.reg[5] = tmp;                                             \
  315.     tmp = S.reg[3];                                             \
  316.     S.reg[3] = S.reg[6];                                        \
  317.     S.reg[6] = tmp;                                             \
  318. }
  319.  
  320. /***************************************************************
  321.  * M_BRR
  322.  * Branch relative if cond is true
  323.  ***************************************************************/
  324. #define M_BRR(cond)                                             \
  325. {                                                                \
  326.     if (cond)                                                    \
  327.     {                                                            \
  328.         REL_EA( S.page );                                        \
  329.         S.page = S.ea & PAGE;                                    \
  330.         S.iar  = S.ea & PMSK;                                    \
  331.         change_pc(S.ea);                                        \
  332.     } else S.iar = (S.iar + 1) & PMSK;                            \
  333. }
  334.  
  335. /***************************************************************
  336.  * M_ZBRR
  337.  * Branch relative to page zero
  338.  ***************************************************************/
  339. #define M_ZBRR()                                                \
  340. {                                                                \
  341.     REL_ZERO( 0 );                                                \
  342.     S.page = S.ea & PAGE;                                        \
  343.     S.iar  = S.ea & PMSK;                                        \
  344.     change_pc(S.ea);                                            \
  345. }
  346.  
  347. /***************************************************************
  348.  * M_BRA
  349.  * Branch absolute if cond is true
  350.  ***************************************************************/
  351. #define M_BRA(cond)                                             \
  352. {                                                                \
  353.     if( cond )                                                    \
  354.     {                                                            \
  355.         BRA_EA();                                                \
  356.         S.page = S.ea & PAGE;                                    \
  357.         S.iar  = S.ea & PMSK;                                    \
  358.         change_pc(S.ea);                                        \
  359.     } else S.iar = (S.iar + 2) & PMSK;                            \
  360. }
  361.  
  362. /***************************************************************
  363.  * M_BXA
  364.  * Branch indexed absolute (EA + R3)
  365.  ***************************************************************/
  366. #define M_BXA()                                                 \
  367. {                                                                \
  368.     BRA_EA();                                                    \
  369.     S.ea   = (S.ea + S.reg[3]) & AMSK;                            \
  370.     S.page = S.ea & PAGE;                                        \
  371.     S.iar  = S.ea & PMSK;                                        \
  372.     change_pc(S.ea);                                            \
  373. }
  374.  
  375. /***************************************************************
  376.  * M_BSR
  377.  * Branch to subroutine relative if cond is true
  378.  ***************************************************************/
  379. #define M_BSR(cond)                                             \
  380. {                                                                \
  381.     if( cond )                                                    \
  382.     {                                                            \
  383.         REL_EA(S.page);                                         \
  384.         S.psu  = (S.psu & ~SP) | ((S.psu + 1) & SP);            \
  385.         S.ras[S.psu & SP] = S.page + S.iar;                        \
  386.         S.page = S.ea & PAGE;                                    \
  387.         S.iar  = S.ea & PMSK;                                    \
  388.         change_pc(S.ea);                                        \
  389.     } else    S.iar = (S.iar + 1) & PMSK;                         \
  390. }
  391.  
  392. /***************************************************************
  393.  * M_ZBSR
  394.  * Branch to subroutine relative to page zero
  395.  ***************************************************************/
  396. #define M_ZBSR()                                                \
  397. {                                                                \
  398.     REL_ZERO(0);                                                 \
  399.     S.psu  = (S.psu & ~SP) | ((S.psu + 1) & SP);                \
  400.     S.ras[S.psu & SP] = S.page + S.iar;                            \
  401.     S.page = S.ea & PAGE;                                        \
  402.     S.iar  = S.ea & PMSK;                                        \
  403.     change_pc(S.ea);                                            \
  404. }
  405.  
  406. /***************************************************************
  407.  * M_BSA
  408.  * Branch to subroutine absolute
  409.  ***************************************************************/
  410. #define M_BSA(cond)                                             \
  411. {                                                                \
  412.     if( cond )                                                    \
  413.     {                                                            \
  414.         BRA_EA();                                                \
  415.         S.psu = (S.psu & ~SP) | ((S.psu + 1) & SP);             \
  416.         S.ras[S.psu & SP] = S.page + S.iar;                        \
  417.         S.page = S.ea & PAGE;                                    \
  418.         S.iar  = S.ea & PMSK;                                    \
  419.         change_pc(S.ea);                                        \
  420.     } else S.iar = (S.iar + 2) & PMSK;                            \
  421. }
  422.  
  423. /***************************************************************
  424.  * M_BSXA
  425.  * Branch to subroutine indexed absolute (EA + R3)
  426.  ***************************************************************/
  427. #define M_BSXA()                                                \
  428. {                                                                \
  429.     BRA_EA();                                                    \
  430.     S.ea  = (S.ea + S.reg[3]) & AMSK;                            \
  431.     S.psu = (S.psu & ~SP) | ((S.psu + 1) & SP);                 \
  432.     S.ras[S.psu & SP] = S.page + S.iar;                            \
  433.     S.page = S.ea & PAGE;                                        \
  434.     S.iar  = S.ea & PMSK;                                        \
  435.     change_pc(S.ea);                                            \
  436. }
  437.  
  438. /***************************************************************
  439.  * M_RET
  440.  * Return from subroutine if cond is true
  441.  ***************************************************************/
  442. #define M_RET(cond)                                             \
  443. {                                                                \
  444.     if( cond )                                                    \
  445.     {                                                            \
  446.         S.ea = S.ras[S.psu & SP];                                \
  447.         S.psu = (S.psu & ~SP) | ((S.psu - 1) & SP);             \
  448.         S.page = S.ea & PAGE;                                    \
  449.         S.iar  = S.ea & PMSK;                                    \
  450.         change_pc(S.ea);                                        \
  451.     }                                                            \
  452. }
  453.  
  454. /***************************************************************
  455.  * M_RETE
  456.  * Return from subroutine if cond is true
  457.  * and enable interrupts; afterwards check IRQ line
  458.  * state and eventually take next interrupt
  459.  ***************************************************************/
  460. #define M_RETE(cond)                                            \
  461. {                                                                \
  462.     if( cond )                                                    \
  463.     {                                                            \
  464.         S.ea = S.ras[S.psu & SP];                                \
  465.         S.psu = (S.psu & ~SP) | ((S.psu - 1) & SP);             \
  466.         S.page = S.ea & PAGE;                                    \
  467.         S.iar  = S.ea & PMSK;                                    \
  468.         change_pc(S.ea);                                        \
  469.         S.psu &= ~II;                                            \
  470.         CHECK_IRQ_LINE;                                         \
  471.     }                                                            \
  472. }
  473.  
  474. /***************************************************************
  475.  * M_LOD
  476.  * Load destination with source register
  477.  ***************************************************************/
  478. #define M_LOD(dest,source)                                        \
  479. {                                                                \
  480.     dest = source;                                                \
  481.     SET_CC(dest);                                                \
  482. }
  483.  
  484. /***************************************************************
  485.  * M_STR
  486.  * Store source register to memory addr (CC unchanged)
  487.  ***************************************************************/
  488. #define M_STR(address,source)                                    \
  489.     cpu_writemem16(address, source)
  490.  
  491. /***************************************************************
  492.  * M_AND
  493.  * Logical and destination with source
  494.  ***************************************************************/
  495. #define M_AND(dest,source)                                        \
  496. {                                                                \
  497.     dest &= source;                                             \
  498.     SET_CC(dest);                                                \
  499. }
  500.  
  501. /***************************************************************
  502.  * M_IOR
  503.  * Logical inclusive or destination with source
  504.  ***************************************************************/
  505. #define M_IOR(dest,source)                                        \
  506. {                                                                \
  507.     dest |= source;                                             \
  508.     SET_CC(dest);                                                \
  509. }
  510.  
  511. /***************************************************************
  512.  * M_EOR
  513.  * Logical exclusive or destination with source
  514.  ***************************************************************/
  515. #define M_EOR(dest,source)                                        \
  516. {                                                                \
  517.     dest ^= source;                                             \
  518.     SET_CC(dest);                                                \
  519. }
  520.  
  521. /***************************************************************
  522.  * M_ADD
  523.  * Add source to destination
  524.  * Add with carry if WC flag of PSL is set
  525.  ***************************************************************/
  526. #define M_ADD(dest,source)                                        \
  527. {                                                                \
  528.     UINT8 before = dest;                                        \
  529.     /* add source; carry only if WC is set */                    \
  530.     dest = dest + source + ((S.psl >> 3) & S.psl & C);            \
  531.     S.psl &= ~(C | OVF | IDC);                                    \
  532.     if( dest < before ) S.psl |= C;                             \
  533.     if( (dest & 15) < (before & 15) ) S.psl |= IDC;             \
  534.     SET_CC_OVF(dest,before);                                    \
  535. }
  536.  
  537. /***************************************************************
  538.  * M_SUB
  539.  * Subtract source from destination
  540.  * Subtract with borrow if WC flag of PSL is set
  541.  ***************************************************************/
  542. #define M_SUB(dest,source)                                        \
  543. {                                                                \
  544.     UINT8 before = dest;                                        \
  545.     /* subtract source; borrow only if WC is set */             \
  546.     dest = dest - source - ((S.psl >> 3) & (S.psl ^ C) & C);    \
  547.     S.psl &= ~(C | OVF | IDC);                                    \
  548.     if( dest <= before ) S.psl |= C;                            \
  549.     if( (dest & 15) < (before & 15) ) S.psl |= IDC;             \
  550.     SET_CC_OVF(dest,before);                                    \
  551. }
  552.  
  553. /***************************************************************
  554.  * M_COM
  555.  * Compare register against value. If COM of PSL is set,
  556.  * use unsigned, else signed comparison
  557.  ***************************************************************/
  558. #define M_COM(reg,val)                                            \
  559. {                                                                \
  560.     int d;                                                        \
  561.     S.psl &= ~CC;                                                \
  562.     if (S.psl & COM) d = (UINT8)reg - (UINT8)val;                \
  563.                 else d = (INT8)reg - (INT8)val;                 \
  564.     if( d < 0 ) S.psl |= 0x80;                                    \
  565.     else                                                        \
  566.     if( d > 0 ) S.psl |= 0x40;                                    \
  567. }
  568.  
  569. /***************************************************************
  570.  * M_DAR
  571.  * Decimal adjust register
  572.  ***************************************************************/
  573. #define M_DAR(dest)                                                \
  574. {                                                                \
  575.     if((S.psl & IDC) != 0)                                        \
  576.     {                                                            \
  577.         if((S.psl & C) == 0) dest -= 0x60;                        \
  578.     }                                                            \
  579.     else                                                        \
  580.     {                                                            \
  581.         if( (S.psl & C) != 0 ) dest -= 0x06;                    \
  582.         else dest -= 0x66;                                        \
  583.     }                                                            \
  584. }
  585.  
  586. /***************************************************************
  587.  * M_RRL
  588.  * Rotate register left; If WC of PSL is set, rotate
  589.  * through carry, else rotate circular
  590.  ***************************************************************/
  591. #define M_RRL(dest)                                             \
  592. {                                                                \
  593.     UINT8 before = dest;                                        \
  594.     if( S.psl & WC )                                            \
  595.     {                                                            \
  596.         UINT8 c = S.psl & C;                                    \
  597.         S.psl &= ~(C + IDC);                                    \
  598.         dest = (before << 1) | c;                                \
  599.         S.psl |= (before >> 7) + (dest & IDC);                    \
  600.     }                                                            \
  601.     else                                                        \
  602.     {                                                            \
  603.         dest = (before << 1) | (before >> 7);                    \
  604.     }                                                            \
  605.     SET_CC_OVF(dest,before);                                    \
  606. }
  607.  
  608. /***************************************************************
  609.  * M_RRR
  610.  * Rotate register right; If WC of PSL is set, rotate
  611.  * through carry, else rotate circular
  612.  ***************************************************************/
  613. #define M_RRR(dest)                                             \
  614. {                                                                \
  615.     UINT8 before = dest;                                        \
  616.     if (S.psl & WC)                                             \
  617.     {                                                            \
  618.         UINT8 c = S.psl & C;                                    \
  619.         S.psl &= ~(C + IDC);                                    \
  620.         dest = (before >> 1) | (c << 7);                        \
  621.         S.psl |= (before & C) + (dest & IDC);                    \
  622.     } else    dest = (before >> 1) | (before << 7);                \
  623.     SET_CC_OVF(dest,before);                                    \
  624. }
  625.  
  626. /***************************************************************
  627.  * M_SPSU
  628.  * Store processor status upper (PSU) to register R0
  629.  ***************************************************************/
  630. #define M_SPSU()                                                \
  631. {                                                                \
  632.     R0 = S.psu & ~PSU34;                                        \
  633.     SET_CC(R0);                                                 \
  634. }
  635.  
  636. /***************************************************************
  637.  * M_SPSL
  638.  * Store processor status lower (PSL) to register R0
  639.  ***************************************************************/
  640. #define M_SPSL()                                                \
  641. {                                                                \
  642.     R0 = S.psl;                                                 \
  643.     SET_CC(R0);                                                 \
  644. }
  645.  
  646. /***************************************************************
  647.  * M_CPSU
  648.  * Clear processor status upper (PSU), selective
  649.  ***************************************************************/
  650. #define M_CPSU()                                                \
  651. {                                                                \
  652.     UINT8 cpsu = ARG();                                         \
  653.     S.psu = S.psu & ~cpsu;                                        \
  654.     CHECK_IRQ_LINE;                                             \
  655. }
  656.  
  657. /***************************************************************
  658.  * M_CPSL
  659.  * Clear processor status lower (PSL), selective
  660.  ***************************************************************/
  661. #define M_CPSL()                                                \
  662. {                                                                \
  663.     UINT8 cpsl = ARG();                                         \
  664.     /* select other register set now ? */                        \
  665.     if( (cpsl & RS) && (S.psl & RS) )                            \
  666.         SWAP_REGS;                                                \
  667.     S.psl = S.psl & ~cpsl;                                        \
  668.     CHECK_IRQ_LINE;                                             \
  669. }
  670.  
  671. /***************************************************************
  672.  * M_PPSU
  673.  * Preset processor status upper (PSU), selective
  674.  * Unused bits 3 and 4 can't be set
  675.  ***************************************************************/
  676. #define M_PPSU()                                                \
  677. {                                                                \
  678.     UINT8 ppsu = ARG() & ~PSU34;                                \
  679.     S.psu = S.psu | ppsu;                                        \
  680. }
  681.  
  682. /***************************************************************
  683.  * M_PPSL
  684.  * Preset processor status lower (PSL), selective
  685.  ***************************************************************/
  686. #define M_PPSL()                                                \
  687. {                                                                \
  688.     UINT8 ppsl = ARG();                                         \
  689.     /* select 2nd register set now ? */                         \
  690.     if ((ppsl & RS) && !(S.psl & RS))                            \
  691.         SWAP_REGS;                                                \
  692.     S.psl = S.psl | ppsl;                                        \
  693. }
  694.  
  695. /***************************************************************
  696.  * M_TPSU
  697.  * Test processor status upper (PSU)
  698.  ***************************************************************/
  699. #define M_TPSU()                                                \
  700. {                                                                \
  701.     UINT8 tpsu = ARG();                                         \
  702.     S.psl &= ~CC;                                                \
  703.     if( (S.psu & tpsu) != tpsu )                                \
  704.         S.psl |= 0x80;                                            \
  705. }
  706.  
  707. /***************************************************************
  708.  * M_TPSL
  709.  * Test processor status lower (PSL)
  710.  ***************************************************************/
  711. #define M_TPSL()                                                \
  712. {                                                                \
  713.     UINT8 tpsl = ARG();                                         \
  714.     if( (S.psl & tpsl) != tpsl )                                \
  715.         S.psl = (S.psl & ~CC) | 0x80;                            \
  716.     else                                                        \
  717.         S.psl &= ~CC;                                            \
  718. }
  719.  
  720. /***************************************************************
  721.  * M_TMI
  722.  * Test under mask immediate
  723.  ***************************************************************/
  724. #define M_TMI(value)                                            \
  725. {                                                                \
  726.     UINT8 tmi = ARG();                                            \
  727.     S.psl &= ~CC;                                                \
  728.     if( (value & tmi) != tmi )                                    \
  729.         S.psl |= 0x80;                                            \
  730. }
  731.  
  732. #if INLINE_EA
  733. #define REL_EA(page) _REL_EA(page)
  734. #define REL_ZERO(page) _REL_ZERO(page)
  735. #define ABS_EA() _ABS_EA()
  736. #define BRA_EA() _BRA_EA()
  737. #else
  738. static void REL_EA(unsigned short page) _REL_EA(page)
  739. static void REL_ZERO(unsigned short page) _REL_ZERO(page)
  740. static void ABS_EA(void) _ABS_EA()
  741. static void BRA_EA(void) _BRA_EA()
  742. #endif
  743.  
  744. void s2650_reset(void *param)
  745. {
  746.     memset(&S, 0, sizeof(S));
  747.     S.psl = COM | WC;
  748.     S.psu = SI;
  749. }
  750.  
  751. void s2650_exit(void)
  752. {
  753.     /* nothing to do */
  754. }
  755.  
  756. unsigned s2650_get_context(void *dst)
  757. {
  758.     if( dst )
  759.         *(s2650_Regs*)dst = S;
  760.     return sizeof(s2650_Regs);
  761. }
  762.  
  763. void s2650_set_context(void *src)
  764. {
  765.     if( src )
  766.     {
  767.         S = *(s2650_Regs*)src;
  768.         S.page = S.page & PAGE;
  769.         S.iar = S.iar & PMSK;
  770.         change_pc(S.page + S.iar);
  771.     }
  772. }
  773.  
  774. unsigned s2650_get_pc(void)
  775. {
  776.     return S.page + S.iar;
  777. }
  778.  
  779. void s2650_set_pc(unsigned val)
  780. {
  781.     S.page = val & PAGE;
  782.     S.iar = val & PMSK;
  783.     change_pc(S.page + S.iar);
  784. }
  785.  
  786. unsigned s2650_get_sp(void)
  787. {
  788.     return S.psu & SP;
  789. }
  790.  
  791. void s2650_set_sp(unsigned val)
  792. {
  793.     S.psu = (S.psu & ~SP) | (val & SP);
  794. }
  795.  
  796. unsigned s2650_get_reg(int regnum)
  797. {
  798.     switch( regnum )
  799.     {
  800.         case S2650_PC: return S.page + S.iar;
  801.         case S2650_PS: return (S.psu << 8) | S.psl;
  802.         case S2650_R0: return S.reg[0];
  803.         case S2650_R1: return S.reg[1];
  804.         case S2650_R2: return S.reg[2];
  805.         case S2650_R3: return S.reg[3];
  806.         case S2650_R1A: return S.reg[4];
  807.         case S2650_R2A: return S.reg[5];
  808.         case S2650_R3A: return S.reg[6];
  809.         case S2650_HALT: return S.halt;
  810.         case S2650_IRQ_STATE: return S.irq_state;
  811.         case S2650_SI: return s2650_get_sense(); break;
  812.         case S2650_FO: return s2650_get_flag(); break;
  813.         case REG_PREVIOUSPC: return S.ppc; break;
  814.         default:
  815.             if( regnum <= REG_SP_CONTENTS )
  816.             {
  817.                 unsigned offset = (REG_SP_CONTENTS - regnum);
  818.                 if( offset < 8 )
  819.                     return S.ras[offset];
  820.             }
  821.     }
  822.     return 0;
  823. }
  824.  
  825. void s2650_set_reg(int regnum, unsigned val)
  826. {
  827.     switch( regnum )
  828.     {
  829.         case S2650_PC: S.page = val & PAGE; S.iar = val & PMSK; break;
  830.         case S2650_PS: S.psl = val & 0xff; S.psu = val >> 8; break;
  831.         case S2650_R0: S.reg[0] = val; break;
  832.         case S2650_R1: S.reg[1] = val; break;
  833.         case S2650_R2: S.reg[2] = val; break;
  834.         case S2650_R3: S.reg[3] = val; break;
  835.         case S2650_R1A: S.reg[4] = val; break;
  836.         case S2650_R2A: S.reg[5] = val; break;
  837.         case S2650_R3A: S.reg[6] = val; break;
  838.         case S2650_HALT: S.halt = val; break;
  839.         case S2650_IRQ_STATE: s2650_set_irq_line(0, val); break;
  840.         case S2650_SI: s2650_set_sense(val); break;
  841.         case S2650_FO: s2650_set_flag(val); break;
  842.         default:
  843.             if( regnum <= REG_SP_CONTENTS )
  844.             {
  845.                 unsigned offset = (REG_SP_CONTENTS - regnum);
  846.                 if( offset < 8 )
  847.                     S.ras[offset] = val;
  848.             }
  849.     }
  850. }
  851.  
  852. void s2650_set_nmi_line(int state)
  853. {
  854.     /* no NMI line */
  855. }
  856.  
  857. void s2650_set_irq_line(int irqline, int state)
  858. {
  859.     if (irqline == 1)
  860.     {
  861.         if (state == CLEAR_LINE)
  862.             s2650_set_sense(0);
  863.         else
  864.             s2650_set_sense(1);
  865.         return;
  866.     }
  867.     S.irq_state = state;
  868.     CHECK_IRQ_LINE;
  869. }
  870.  
  871. void s2650_set_irq_callback(int (*callback)(int irqline))
  872. {
  873.     S.irq_callback = callback;
  874. }
  875.  
  876. void s2650_set_flag(int state)
  877. {
  878.     if (state)
  879.         S.psu |= FO;
  880.     else
  881.         S.psu &= ~FO;
  882. }
  883.  
  884. int s2650_get_flag(void)
  885. {
  886.     return (S.psu & FO) ? 1 : 0;
  887. }
  888.  
  889. void s2650_set_sense(int state)
  890. {
  891.     if (state)
  892.         S.psu |= SI;
  893.     else
  894.         S.psu &= ~SI;
  895. }
  896.  
  897. int s2650_get_sense(void)
  898. {
  899.     return (S.psu & SI) ? 1 : 0;
  900. }
  901.  
  902. static  int S2650_Cycles[0x100] = {
  903.     2,2,2,2, 2,2,2,2, 3,3,3,3, 4,4,4,4,
  904.     2,2,2,2, 2,2,2,2, 3,3,3,3, 3,3,3,3,
  905.     2,2,2,2, 2,2,2,2, 3,3,3,3, 4,4,4,4,
  906.     2,2,2,2, 3,3,3,3, 3,3,3,3, 3,3,3,3,
  907.     2,2,2,2, 2,2,2,2, 3,3,3,3, 4,4,4,4,
  908.     2,2,2,2, 3,3,3,3, 3,3,3,3, 3,3,3,3,
  909.     2,2,2,2, 2,2,2,2, 3,3,3,3, 4,4,4,4,
  910.     2,2,2,2, 2,2,2,2, 3,3,3,3, 3,3,3,3,
  911.     2,2,2,2, 2,2,2,2, 3,3,3,3, 4,4,4,4,
  912.     2,2,2,2, 2,2,2,2, 3,3,3,3, 3,3,3,3,
  913.     2,2,2,2, 2,2,2,2, 3,3,3,3, 4,4,4,4,
  914.     2,2,2,2, 2,2,2,2, 3,3,3,3, 3,3,3,3,
  915.     2,2,2,2, 2,2,2,2, 3,3,3,3, 4,4,4,4,
  916.     2,2,2,2, 3,3,3,3, 3,3,3,3, 3,3,3,3,
  917.     2,2,2,2, 2,2,2,2, 3,3,3,3, 4,4,4,4,
  918.     2,2,2,2, 3,3,3,3, 3,3,3,3, 3,3,3,3
  919. };
  920.  
  921. int s2650_execute(int cycles)
  922. {
  923.     s2650_ICount = cycles;
  924.     do
  925.     {
  926.         S.ppc = S.page + S.iar;
  927.  
  928.         CALL_MAME_DEBUG;
  929.  
  930.         S.ir = ROP();
  931.         s2650_ICount -= S2650_Cycles[S.ir];
  932.         S.r = S.ir & 3;         /* register / value */
  933.         switch (S.ir) {
  934.             case 0x00:        /* LODZ,0 */
  935.             case 0x01:        /* LODZ,1 */
  936.             case 0x02:        /* LODZ,2 */
  937.             case 0x03:        /* LODZ,3 */
  938.                 M_LOD( R0, S.reg[S.r] );
  939.                 break;
  940.  
  941.             case 0x04:        /* LODI,0 v */
  942.             case 0x05:        /* LODI,1 v */
  943.             case 0x06:        /* LODI,2 v */
  944.             case 0x07:        /* LODI,3 v */
  945.                 M_LOD( S.reg[S.r], ARG() );
  946.                 break;
  947.  
  948.             case 0x08:        /* LODR,0 (*)a */
  949.             case 0x09:        /* LODR,1 (*)a */
  950.             case 0x0a:        /* LODR,2 (*)a */
  951.             case 0x0b:        /* LODR,3 (*)a */
  952.                 REL_EA( S.page );
  953.                 M_LOD( S.reg[S.r], RDMEM(S.ea) );
  954.                 break;
  955.  
  956.             case 0x0c:        /* LODA,0 (*)a(,X) */
  957.             case 0x0d:        /* LODA,1 (*)a(,X) */
  958.             case 0x0e:        /* LODA,2 (*)a(,X) */
  959.             case 0x0f:        /* LODA,3 (*)a(,X) */
  960.                 ABS_EA();
  961.                 M_LOD( S.reg[S.r], RDMEM(S.ea) );
  962.                 break;
  963.  
  964.             case 0x10:        /* illegal */
  965.             case 0x11:        /* illegal */
  966.                 break;
  967.             case 0x12:        /* SPSU */
  968.                 M_SPSU();
  969.                 break;
  970.             case 0x13:        /* SPSL */
  971.                 M_SPSL();
  972.                 break;
  973.  
  974.             case 0x14:        /* RETC,0    (zero)    */
  975.             case 0x15:        /* RETC,1    (plus)    */
  976.             case 0x16:        /* RETC,2    (minus) */
  977.                 M_RET( (S.psl >> 6) == S.r );
  978.                 break;
  979.             case 0x17:        /* RETC,3    (always) */
  980.                 M_RET( 1 );
  981.                 break;
  982.  
  983.             case 0x18:        /* BCTR,0  (*)a */
  984.             case 0x19:        /* BCTR,1  (*)a */
  985.             case 0x1a:        /* BCTR,2  (*)a */
  986.                 M_BRR( (S.psl >> 6) == S.r );
  987.                 break;
  988.             case 0x1b:        /* BCTR,3  (*)a */
  989.                 M_BRR( 1 );
  990.                 break;
  991.  
  992.             case 0x1c:        /* BCTA,0  (*)a */
  993.             case 0x1d:        /* BCTA,1  (*)a */
  994.             case 0x1e:        /* BCTA,2  (*)a */
  995.                 M_BRA( (S.psl >> 6) == S.r );
  996.                 break;
  997.             case 0x1f:        /* BCTA,3  (*)a */
  998.                 M_BRA( 1 );
  999.                 break;
  1000.  
  1001.             case 0x20:        /* EORZ,0 */
  1002.             case 0x21:        /* EORZ,1 */
  1003.             case 0x22:        /* EORZ,2 */
  1004.             case 0x23:        /* EORZ,3 */
  1005.                 M_EOR( R0, S.reg[S.r] );
  1006.                 break;
  1007.  
  1008.             case 0x24:        /* EORI,0 v */
  1009.             case 0x25:        /* EORI,1 v */
  1010.             case 0x26:        /* EORI,2 v */
  1011.             case 0x27:        /* EORI,3 v */
  1012.                 M_EOR( S.reg[S.r], ARG() );
  1013.                 break;
  1014.  
  1015.             case 0x28:        /* EORR,0 (*)a */
  1016.             case 0x29:        /* EORR,1 (*)a */
  1017.             case 0x2a:        /* EORR,2 (*)a */
  1018.             case 0x2b:        /* EORR,3 (*)a */
  1019.                 REL_EA( S.page );
  1020.                 M_EOR( S.reg[S.r], RDMEM(S.ea) );
  1021.                 break;
  1022.  
  1023.             case 0x2c:        /* EORA,0 (*)a(,X) */
  1024.             case 0x2d:        /* EORA,1 (*)a(,X) */
  1025.             case 0x2e:        /* EORA,2 (*)a(,X) */
  1026.             case 0x2f:        /* EORA,3 (*)a(,X) */
  1027.                 ABS_EA();
  1028.                 M_EOR( S.reg[S.r], RDMEM(S.ea) );
  1029.                 break;
  1030.  
  1031.             case 0x30:        /* REDC,0 */
  1032.             case 0x31:        /* REDC,1 */
  1033.             case 0x32:        /* REDC,2 */
  1034.             case 0x33:        /* REDC,3 */
  1035.                 S.reg[S.r] = cpu_readport(S2650_CTRL_PORT);
  1036.                 SET_CC( S.reg[S.r] );
  1037.                 break;
  1038.  
  1039.             case 0x34:        /* RETE,0 */
  1040.             case 0x35:        /* RETE,1 */
  1041.             case 0x36:        /* RETE,2 */
  1042.                 M_RETE( (S.psl >> 6) == S.r );
  1043.                 break;
  1044.             case 0x37:        /* RETE,3 */
  1045.                 M_RETE( 1 );
  1046.                 break;
  1047.  
  1048.             case 0x38:        /* BSTR,0 (*)a */
  1049.             case 0x39:        /* BSTR,1 (*)a */
  1050.             case 0x3a:        /* BSTR,2 (*)a */
  1051.                 M_BSR( (S.psl >> 6) == S.r );
  1052.                 break;
  1053.             case 0x3b:        /* BSTR,R3 (*)a */
  1054.                 M_BSR( 1 );
  1055.                 break;
  1056.  
  1057.             case 0x3c:        /* BSTA,0 (*)a */
  1058.             case 0x3d:        /* BSTA,1 (*)a */
  1059.             case 0x3e:        /* BSTA,2 (*)a */
  1060.                 M_BSA( (S.psl >> 6) == S.r );
  1061.                 break;
  1062.             case 0x3f:        /* BSTA,3 (*)a */
  1063.                 M_BSA( 1 );
  1064.                 break;
  1065.  
  1066.             case 0x40:        /* HALT */
  1067.                 S.iar = (S.iar - 1) & PMSK;
  1068.                 S.halt = 1;
  1069.                 if (s2650_ICount > 0)
  1070.                     s2650_ICount = 0;
  1071.                 break;
  1072.             case 0x41:        /* ANDZ,1 */
  1073.             case 0x42:        /* ANDZ,2 */
  1074.             case 0x43:        /* ANDZ,3 */
  1075.                 M_AND( R0, S.reg[S.r] );
  1076.                 break;
  1077.  
  1078.             case 0x44:        /* ANDI,0 v */
  1079.             case 0x45:        /* ANDI,1 v */
  1080.             case 0x46:        /* ANDI,2 v */
  1081.             case 0x47:        /* ANDI,3 v */
  1082.                 M_AND( S.reg[S.r], ARG() );
  1083.                 break;
  1084.  
  1085.             case 0x48:        /* ANDR,0 (*)a */
  1086.             case 0x49:        /* ANDR,1 (*)a */
  1087.             case 0x4a:        /* ANDR,2 (*)a */
  1088.             case 0x4b:        /* ANDR,3 (*)a */
  1089.                 REL_EA( S.page );
  1090.                 M_AND( S.reg[S.r], RDMEM(S.ea) );
  1091.                 break;
  1092.  
  1093.             case 0x4c:        /* ANDA,0 (*)a(,X) */
  1094.             case 0x4d:        /* ANDA,1 (*)a(,X) */
  1095.             case 0x4e:        /* ANDA,2 (*)a(,X) */
  1096.             case 0x4f:        /* ANDA,3 (*)a(,X) */
  1097.                 ABS_EA();
  1098.                 M_AND( S.reg[S.r], RDMEM(S.ea) );
  1099.                 break;
  1100.  
  1101.             case 0x50:        /* RRR,0 */
  1102.             case 0x51:        /* RRR,1 */
  1103.             case 0x52:        /* RRR,2 */
  1104.             case 0x53:        /* RRR,3 */
  1105.                 M_RRR( S.reg[S.r] );
  1106.                 break;
  1107.  
  1108.             case 0x54:        /* REDE,0 v */
  1109.             case 0x55:        /* REDE,1 v */
  1110.             case 0x56:        /* REDE,2 v */
  1111.             case 0x57:        /* REDE,3 v */
  1112.                 S.reg[S.r] = cpu_readport( ARG() );
  1113.                 SET_CC(S.reg[S.r]);
  1114.                 break;
  1115.  
  1116.             case 0x58:        /* BRNR,0 (*)a */
  1117.             case 0x59:        /* BRNR,1 (*)a */
  1118.             case 0x5a:        /* BRNR,2 (*)a */
  1119.             case 0x5b:        /* BRNR,3 (*)a */
  1120.                 M_BRR( S.reg[S.r] );
  1121.                 break;
  1122.  
  1123.             case 0x5c:        /* BRNA,0 (*)a */
  1124.             case 0x5d:        /* BRNA,1 (*)a */
  1125.             case 0x5e:        /* BRNA,2 (*)a */
  1126.             case 0x5f:        /* BRNA,3 (*)a */
  1127.                 M_BRA( S.reg[S.r] );
  1128.                 break;
  1129.  
  1130.             case 0x60:        /* IORZ,0 */
  1131.             case 0x61:        /* IORZ,1 */
  1132.             case 0x62:        /* IORZ,2 */
  1133.             case 0x63:        /* IORZ,3 */
  1134.                 M_IOR( R0, S.reg[S.r] );
  1135.                 break;
  1136.  
  1137.             case 0x64:        /* IORI,0 v */
  1138.             case 0x65:        /* IORI,1 v */
  1139.             case 0x66:        /* IORI,2 v */
  1140.             case 0x67:        /* IORI,3 v */
  1141.                 M_IOR( S.reg[S.r], ARG() );
  1142.                 break;
  1143.  
  1144.             case 0x68:        /* IORR,0 (*)a */
  1145.             case 0x69:        /* IORR,1 (*)a */
  1146.             case 0x6a:        /* IORR,2 (*)a */
  1147.             case 0x6b:        /* IORR,3 (*)a */
  1148.                 REL_EA( S.page );
  1149.                 M_IOR( S.reg[S. r],RDMEM(S.ea) );
  1150.                 break;
  1151.  
  1152.             case 0x6c:        /* IORA,0 (*)a(,X) */
  1153.             case 0x6d:        /* IORA,1 (*)a(,X) */
  1154.             case 0x6e:        /* IORA,2 (*)a(,X) */
  1155.             case 0x6f:        /* IORA,3 (*)a(,X) */
  1156.                 ABS_EA();
  1157.                 M_IOR( S.reg[S.r], RDMEM(S.ea) );
  1158.                 break;
  1159.  
  1160.             case 0x70:        /* REDD,0 */
  1161.             case 0x71:        /* REDD,1 */
  1162.             case 0x72:        /* REDD,2 */
  1163.             case 0x73:        /* REDD,3 */
  1164.                 S.reg[S.r] = cpu_readport(S2650_DATA_PORT);
  1165.                 SET_CC(S.reg[S.r]);
  1166.                 break;
  1167.  
  1168.             case 0x74:        /* CPSU */
  1169.                 M_CPSU();
  1170.                 break;
  1171.             case 0x75:        /* CPSL */
  1172.                 M_CPSL();
  1173.                 break;
  1174.             case 0x76:        /* PPSU */
  1175.                 M_PPSU();
  1176.                 break;
  1177.             case 0x77:        /* PPSL */
  1178.                 M_PPSL();
  1179.                 break;
  1180.  
  1181.             case 0x78:        /* BSNR,0 (*)a */
  1182.             case 0x79:        /* BSNR,1 (*)a */
  1183.             case 0x7a:        /* BSNR,2 (*)a */
  1184.             case 0x7b:        /* BSNR,3 (*)a */
  1185.                 M_BSR( S.reg[S.r] );
  1186.                 break;
  1187.  
  1188.             case 0x7c:        /* BSNA,0 (*)a */
  1189.             case 0x7d:        /* BSNA,1 (*)a */
  1190.             case 0x7e:        /* BSNA,2 (*)a */
  1191.             case 0x7f:        /* BSNA,3 (*)a */
  1192.                 M_BSA( S.reg[S.r] );
  1193.                 break;
  1194.  
  1195.             case 0x80:        /* ADDZ,0 */
  1196.             case 0x81:        /* ADDZ,1 */
  1197.             case 0x82:        /* ADDZ,2 */
  1198.             case 0x83:        /* ADDZ,3 */
  1199.                 M_ADD( R0,S.reg[S.r] );
  1200.                 break;
  1201.  
  1202.             case 0x84:        /* ADDI,0 v */
  1203.             case 0x85:        /* ADDI,1 v */
  1204.             case 0x86:        /* ADDI,2 v */
  1205.             case 0x87:        /* ADDI,3 v */
  1206.                 M_ADD( S.reg[S.r], ARG() );
  1207.                 break;
  1208.  
  1209.             case 0x88:        /* ADDR,0 (*)a */
  1210.             case 0x89:        /* ADDR,1 (*)a */
  1211.             case 0x8a:        /* ADDR,2 (*)a */
  1212.             case 0x8b:        /* ADDR,3 (*)a */
  1213.                 REL_EA(S.page);
  1214.                 M_ADD( S.reg[S.r], RDMEM(S.ea) );
  1215.                 break;
  1216.  
  1217.             case 0x8c:        /* ADDA,0 (*)a(,X) */
  1218.             case 0x8d:        /* ADDA,1 (*)a(,X) */
  1219.             case 0x8e:        /* ADDA,2 (*)a(,X) */
  1220.             case 0x8f:        /* ADDA,3 (*)a(,X) */
  1221.                 ABS_EA();
  1222.                 M_ADD( S.reg[S.r], RDMEM(S.ea) );
  1223.                 break;
  1224.  
  1225.             case 0x90:        /* illegal */
  1226.             case 0x91:        /* illegal */
  1227.                 break;
  1228.             case 0x92:        /* LPSU */
  1229.                 S.psu = R0 & ~PSU34;
  1230.                 break;
  1231.             case 0x93:        /* LPSL */
  1232.                 /* change register set ? */
  1233.                 if ((S.psl ^ R0) & RS)
  1234.                     SWAP_REGS;
  1235.                 S.psl = R0;
  1236.                 break;
  1237.  
  1238.             case 0x94:        /* DAR,0 */
  1239.             case 0x95:        /* DAR,1 */
  1240.             case 0x96:        /* DAR,2 */
  1241.             case 0x97:        /* DAR,3 */
  1242.                 M_DAR( S.reg[S.r] );
  1243.                 break;
  1244.  
  1245.             case 0x98:        /* BCFR,0 (*)a */
  1246.             case 0x99:        /* BCFR,1 (*)a */
  1247.             case 0x9a:        /* BCFR,2 (*)a */
  1248.                 M_BRR( (S.psl >> 6) != S.r );
  1249.                 break;
  1250.             case 0x9b:        /* ZBRR    (*)a */
  1251.                 M_ZBRR();
  1252.                 break;
  1253.  
  1254.             case 0x9c:        /* BCFA,0 (*)a */
  1255.             case 0x9d:        /* BCFA,1 (*)a */
  1256.             case 0x9e:        /* BCFA,2 (*)a */
  1257.                 M_BRA( (S.psl >> 6) != S.r );
  1258.                 break;
  1259.             case 0x9f:        /* BXA       (*)a */
  1260.                 M_BXA();
  1261.                 break;
  1262.  
  1263.             case 0xa0:        /* SUBZ,0 */
  1264.             case 0xa1:        /* SUBZ,1 */
  1265.             case 0xa2:        /* SUBZ,2 */
  1266.             case 0xa3:        /* SUBZ,3 */
  1267.                 M_SUB( R0, S.reg[S.r] );
  1268.                 break;
  1269.  
  1270.             case 0xa4:        /* SUBI,0 v */
  1271.             case 0xa5:        /* SUBI,1 v */
  1272.             case 0xa6:        /* SUBI,2 v */
  1273.             case 0xa7:        /* SUBI,3 v */
  1274.                 M_SUB( S.reg[S.r], ARG() );
  1275.                 break;
  1276.  
  1277.             case 0xa8:        /* SUBR,0 (*)a */
  1278.             case 0xa9:        /* SUBR,1 (*)a */
  1279.             case 0xaa:        /* SUBR,2 (*)a */
  1280.             case 0xab:        /* SUBR,3 (*)a */
  1281.                 REL_EA(S.page);
  1282.                 M_SUB( S.reg[S.r], RDMEM(S.ea) );
  1283.                 break;
  1284.  
  1285.             case 0xac:        /* SUBA,0 (*)a(,X) */
  1286.             case 0xad:        /* SUBA,1 (*)a(,X) */
  1287.             case 0xae:        /* SUBA,2 (*)a(,X) */
  1288.             case 0xaf:        /* SUBA,3 (*)a(,X) */
  1289.                 ABS_EA();
  1290.                 M_SUB( S.reg[S.r], RDMEM(S.ea) );
  1291.                 break;
  1292.  
  1293.             case 0xb0:        /* WRTC,0 */
  1294.             case 0xb1:        /* WRTC,1 */
  1295.             case 0xb2:        /* WRTC,2 */
  1296.             case 0xb3:        /* WRTC,3 */
  1297.                 cpu_writeport(S2650_CTRL_PORT,S.reg[S.r]);
  1298.                 break;
  1299.  
  1300.             case 0xb4:        /* TPSU */
  1301.                 M_TPSU();
  1302.                 break;
  1303.             case 0xb5:        /* TPSL */
  1304.                 M_TPSL();
  1305.                 break;
  1306.             case 0xb6:        /* illegal */
  1307.             case 0xb7:        /* illegal */
  1308.                 break;
  1309.  
  1310.             case 0xb8:        /* BSFR,0 (*)a */
  1311.             case 0xb9:        /* BSFR,1 (*)a */
  1312.             case 0xba:        /* BSFR,2 (*)a */
  1313.                 M_BSR( (S.psl >> 6) != S.r );
  1314.                 break;
  1315.             case 0xbb:        /* ZBSR    (*)a */
  1316.                 M_ZBSR();
  1317.                 break;
  1318.  
  1319.             case 0xbc:        /* BSFA,0 (*)a */
  1320.             case 0xbd:        /* BSFA,1 (*)a */
  1321.             case 0xbe:        /* BSFA,2 (*)a */
  1322.                 M_BSA( (S.psl >> 6) != S.r );
  1323.                 break;
  1324.             case 0xbf:        /* BSXA    (*)a */
  1325.                 M_BSXA();
  1326.                 break;
  1327.  
  1328.             case 0xc0:        /* NOP */
  1329.                 break;
  1330.             case 0xc1:        /* STRZ,1 */
  1331.             case 0xc2:        /* STRZ,2 */
  1332.             case 0xc3:        /* STRZ,3 */
  1333.                 M_LOD( S.reg[S.r], R0 );
  1334.                 break;
  1335.  
  1336.             case 0xc4:        /* illegal */
  1337.             case 0xc5:        /* illegal */
  1338.             case 0xc6:        /* illegal */
  1339.             case 0xc7:        /* illegal */
  1340.                 break;
  1341.  
  1342.             case 0xc8:        /* STRR,0 (*)a */
  1343.             case 0xc9:        /* STRR,1 (*)a */
  1344.             case 0xca:        /* STRR,2 (*)a */
  1345.             case 0xcb:        /* STRR,3 (*)a */
  1346.                 REL_EA(S.page);
  1347.                 M_STR( S.ea, S.reg[S.r] );
  1348.                 break;
  1349.  
  1350.             case 0xcc:        /* STRA,0 (*)a(,X) */
  1351.             case 0xcd:        /* STRA,1 (*)a(,X) */
  1352.             case 0xce:        /* STRA,2 (*)a(,X) */
  1353.             case 0xcf:        /* STRA,3 (*)a(,X) */
  1354.                 ABS_EA();
  1355.                 M_STR( S.ea, S.reg[S.r] );
  1356.                 break;
  1357.  
  1358.             case 0xd0:        /* RRL,0 */
  1359.             case 0xd1:        /* RRL,1 */
  1360.             case 0xd2:        /* RRL,2 */
  1361.             case 0xd3:        /* RRL,3 */
  1362.                 M_RRL( S.reg[S.r] );
  1363.                 break;
  1364.  
  1365.             case 0xd4:        /* WRTE,0 v */
  1366.             case 0xd5:        /* WRTE,1 v */
  1367.             case 0xd6:        /* WRTE,2 v */
  1368.             case 0xd7:        /* WRTE,3 v */
  1369.                 cpu_writeport( ARG(), S.reg[S.r] );
  1370.                 break;
  1371.  
  1372.             case 0xd8:        /* BIRR,0 (*)a */
  1373.             case 0xd9:        /* BIRR,1 (*)a */
  1374.             case 0xda:        /* BIRR,2 (*)a */
  1375.             case 0xdb:        /* BIRR,3 (*)a */
  1376.                 M_BRR( ++S.reg[S.r] );
  1377.                 break;
  1378.  
  1379.             case 0xdc:        /* BIRA,0 (*)a */
  1380.             case 0xdd:        /* BIRA,1 (*)a */
  1381.             case 0xde:        /* BIRA,2 (*)a */
  1382.             case 0xdf:        /* BIRA,3 (*)a */
  1383.                 M_BRA( ++S.reg[S.r] );
  1384.                 break;
  1385.  
  1386.             case 0xe0:        /* COMZ,0 */
  1387.             case 0xe1:        /* COMZ,1 */
  1388.             case 0xe2:        /* COMZ,2 */
  1389.             case 0xe3:        /* COMZ,3 */
  1390.                 M_COM( R0, S.reg[S.r] );
  1391.                 break;
  1392.  
  1393.             case 0xe4:        /* COMI,0 v */
  1394.             case 0xe5:        /* COMI,1 v */
  1395.             case 0xe6:        /* COMI,2 v */
  1396.             case 0xe7:        /* COMI,3 v */
  1397.                 M_COM( S.reg[S.r], ARG() );
  1398.                 break;
  1399.  
  1400.             case 0xe8:        /* COMR,0 (*)a */
  1401.             case 0xe9:        /* COMR,1 (*)a */
  1402.             case 0xea:        /* COMR,2 (*)a */
  1403.             case 0xeb:        /* COMR,3 (*)a */
  1404.                 REL_EA(S.page);
  1405.                 M_COM( S.reg[S.r], RDMEM(S.ea) );
  1406.                 break;
  1407.  
  1408.             case 0xec:        /* COMA,0 (*)a(,X) */
  1409.             case 0xed:        /* COMA,1 (*)a(,X) */
  1410.             case 0xee:        /* COMA,2 (*)a(,X) */
  1411.             case 0xef:        /* COMA,3 (*)a(,X) */
  1412.                 ABS_EA();
  1413.                 M_COM( S.reg[S.r], RDMEM(S.ea) );
  1414.                 break;
  1415.  
  1416.             case 0xf0:        /* WRTD,0 */
  1417.             case 0xf1:        /* WRTD,1 */
  1418.             case 0xf2:        /* WRTD,2 */
  1419.             case 0xf3:        /* WRTD,3 */
  1420.                 cpu_writeport(S2650_DATA_PORT, S.reg[S.r]);
  1421.                 break;
  1422.  
  1423.             case 0xf4:        /* TMI,0  v */
  1424.             case 0xf5:        /* TMI,1  v */
  1425.             case 0xf6:        /* TMI,2  v */
  1426.             case 0xf7:        /* TMI,3  v */
  1427.                 M_TMI( S.reg[S.r] );
  1428.                 break;
  1429.  
  1430.             case 0xf8:        /* BDRR,0 (*)a */
  1431.             case 0xf9:        /* BDRR,1 (*)a */
  1432.             case 0xfa:        /* BDRR,2 (*)a */
  1433.             case 0xfb:        /* BDRR,3 (*)a */
  1434.                 M_BRR( --S.reg[S.r] );
  1435.                 break;
  1436.  
  1437.             case 0xfc:        /* BDRA,0 (*)a */
  1438.             case 0xfd:        /* BDRA,1 (*)a */
  1439.             case 0xfe:        /* BDRA,2 (*)a */
  1440.             case 0xff:        /* BDRA,3 (*)a */
  1441.                 M_BRA( --S.reg[S.r] );
  1442.                 break;
  1443.         }
  1444.     } while( s2650_ICount > 0 );
  1445.  
  1446.     return cycles - s2650_ICount;
  1447. }
  1448.  
  1449. void s2650_state_save(void *file)
  1450. {
  1451.     int cpu = cpu_getactivecpu();
  1452.     state_save_UINT16(file,"s2650",cpu,"PAGE",&S.page,1);
  1453.     state_save_UINT16(file,"s2650",cpu,"IAR",&S.iar,1);
  1454.     state_save_UINT8(file,"s2650",cpu,"PSL",&S.psl,1);
  1455.     state_save_UINT8(file,"s2650",cpu,"PSU",&S.psu,1);
  1456.     state_save_UINT8(file,"s2650",cpu,"REG",S.reg,7);
  1457.     state_save_UINT8(file,"s2650",cpu,"HALT",&S.halt,1);
  1458.     state_save_UINT16(file,"s2650",cpu,"RAS",S.ras,8);
  1459.     state_save_UINT8(file,"s2650",cpu,"IRQ_STATE",&S.irq_state,1);
  1460. }
  1461.  
  1462. void s2650_state_load(void *file)
  1463. {
  1464.     int cpu = cpu_getactivecpu();
  1465.     state_load_UINT16(file,"s2650",cpu,"PAGE",&S.page,1);
  1466.     state_load_UINT16(file,"s2650",cpu,"IAR",&S.iar,1);
  1467.     state_load_UINT8(file,"s2650",cpu,"PSL",&S.psl,1);
  1468.     state_load_UINT8(file,"s2650",cpu,"PSU",&S.psu,1);
  1469.     state_load_UINT8(file,"s2650",cpu,"REG",S.reg,7);
  1470.     state_load_UINT8(file,"s2650",cpu,"HALT",&S.halt,1);
  1471.     state_load_UINT16(file,"s2650",cpu,"RAS",S.ras,8);
  1472.     state_load_UINT8(file,"s2650",cpu,"IRQ_STATE",&S.irq_state,1);
  1473. }
  1474.  
  1475. /****************************************************************************
  1476.  * Return a formatted string for a register
  1477.  ****************************************************************************/
  1478. const char *s2650_info(void *context, int regnum)
  1479. {
  1480.     static char buffer[16][47+1];
  1481.     static int which = 0;
  1482.     s2650_Regs *r = context;
  1483.  
  1484.     which = ++which % 16;
  1485.     buffer[which][0] = '\0';
  1486.  
  1487.     if( !context )
  1488.         r = &S;
  1489.  
  1490.     switch( regnum )
  1491.     {
  1492.         case CPU_INFO_FLAGS:
  1493.         case CPU_INFO_REG+S2650_PC: sprintf(buffer[which], "PC:%04X", r->page + r->iar); break;
  1494.         case CPU_INFO_REG+S2650_PS: sprintf(buffer[which], "PS:%02X%02X", r->psu, r->psl); break;
  1495.         case CPU_INFO_REG+S2650_R0: sprintf(buffer[which], "R0:%02X", r->reg[0]); break;
  1496.         case CPU_INFO_REG+S2650_R1: sprintf(buffer[which], "R1:%02X", r->reg[1]); break;
  1497.         case CPU_INFO_REG+S2650_R2: sprintf(buffer[which], "R2:%02X", r->reg[2]); break;
  1498.         case CPU_INFO_REG+S2650_R3: sprintf(buffer[which], "R3:%02X", r->reg[3]); break;
  1499.         case CPU_INFO_REG+S2650_R1A: sprintf(buffer[which], "R1'%02X", r->reg[4]); break;
  1500.         case CPU_INFO_REG+S2650_R2A: sprintf(buffer[which], "R2'%02X", r->reg[5]); break;
  1501.         case CPU_INFO_REG+S2650_R3A: sprintf(buffer[which], "R3'%02X", r->reg[6]); break;
  1502.         case CPU_INFO_REG+S2650_HALT: sprintf(buffer[which], "HALT:%X", r->halt); break;
  1503.         case CPU_INFO_REG+S2650_IRQ_STATE: sprintf(buffer[which], "IRQ:%X", r->irq_state); break;
  1504.         case CPU_INFO_REG+S2650_SI: sprintf(buffer[which], "SI:%X", (r->psu & SI) ? 1 : 0); break;
  1505.         case CPU_INFO_REG+S2650_FO: sprintf(buffer[which], "FO:%X", (r->psu & FO) ? 1 : 0); break;
  1506.             sprintf(buffer[which], "%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c",
  1507.                 r->psu & 0x80 ? 'S':'.',
  1508.                 r->psu & 0x40 ? 'O':'.',
  1509.                 r->psu & 0x20 ? 'I':'.',
  1510.                 r->psu & 0x10 ? '?':'.',
  1511.                 r->psu & 0x08 ? '?':'.',
  1512.                 r->psu & 0x04 ? 's':'.',
  1513.                 r->psu & 0x02 ? 's':'.',
  1514.                 r->psu & 0x01 ? 's':'.',
  1515.                 r->psl & 0x80 ? 'M':'.',
  1516.                 r->psl & 0x40 ? 'P':'.',
  1517.                 r->psl & 0x20 ? 'H':'.',
  1518.                 r->psl & 0x10 ? 'R':'.',
  1519.                 r->psl & 0x08 ? 'W':'.',
  1520.                 r->psl & 0x04 ? 'V':'.',
  1521.                 r->psl & 0x02 ? '2':'.',
  1522.                 r->psl & 0x01 ? 'C':'.');
  1523.             break;
  1524.         case CPU_INFO_NAME: return "S2650";
  1525.         case CPU_INFO_FAMILY: return "Signetics 2650";
  1526.         case CPU_INFO_VERSION: return "1.1";
  1527.         case CPU_INFO_FILE: return __FILE__;
  1528.         case CPU_INFO_CREDITS: return "Written by Juergen Buchmueller for use with MAME";
  1529.         case CPU_INFO_REG_LAYOUT: return (const char *)s2650_reg_layout;
  1530.         case CPU_INFO_WIN_LAYOUT: return (const char *)s2650_win_layout;
  1531.     }
  1532.     return buffer[which];
  1533. }
  1534.  
  1535. unsigned s2650_dasm(char *buffer, unsigned pc)
  1536. {
  1537. #ifdef MAME_DEBUG
  1538.     return Dasm2650(buffer,pc);
  1539. #else
  1540.     sprintf( buffer, "$%02X", cpu_readop(pc) );
  1541.     return 1;
  1542. #endif
  1543. }
  1544.  
  1545.